package cn.ibdsr.human.util;


import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;

/**
 * @author chenglx
 * @version V1.0
 * @description AES对称加解密工具类
 * @createDate 2020/3/26 19:50
 * <p>
 * Date Author Description
 * ------------------------------------------------------
 * 2020/3/26 chenglx init
 */
@Slf4j
public class AesCryptUtils {

    private static final String AES_ALGORITHM = "AES";
    private static final String AES_CBC_PKCS7PADDING = "AES/CBC/PKCS7Padding";

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 对按 AES/CBC/PKCS7Padding 加密过的数据进行解密
     * @param secretKey 密钥
     * @param initialVector 初始向量
     * @param encryptedData 加密数据
     * @return 字节数组形式的解密数据
     */
    public static byte[] decryptAesCbcPkcs7Data(String secretKey, String initialVector, String encryptedData) {
        if (StringUtils.isEmpty(secretKey) || StringUtils.isEmpty(initialVector) || StringUtils.isEmpty(encryptedData)) {
            log.warn("decryptAesCbcPkcs7Data(): 参数不全：secretKey={}, initialVector={}, encryptedData={}",
                    secretKey, initialVector, encryptedData);
            return null;
        }

        byte[] keyBytes = Base64Utils.decodeFromString(secretKey);
//        log.info("secretKey: {}, keyBytes.length={}, keyBytes: {}", secretKey, keyBytes.length, Arrays.toString(keyBytes));
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, AES_ALGORITHM);

        byte[] ivBytes = Base64Utils.decodeFromString(initialVector);
//        log.info("initialVector: {}, ivBytes.length={}, ivBytes: {}", initialVector, ivBytes.length, Arrays.toString(ivBytes));
        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);

        byte[] encryptedDataBytes = Base64Utils.decodeFromString(encryptedData);
//        log.info("encryptedData: {}, ivBytes.length={}, ivBytes: {}", encryptedData, encryptedDataBytes.length, Arrays.toString(encryptedDataBytes));

        try {
            Cipher cipher = Cipher.getInstance(AES_CBC_PKCS7PADDING);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            return cipher.doFinal(encryptedDataBytes);
        } catch (Exception e) {
            log.error("decryptAesCbcPkcs7Data(): 解密数据发生异常: initialVector={}", initialVector, e);
            return null;
        }
    }

    public static void main(String[] args) {
        System.out.println("hello");

        System.out.println("decrypted: " + new String(decryptAesCbcPkcs7Data("pFLM/R+2JNKeSO8QlqYCdw==", "oQ3mCVcKZNGlliAZa30+zA==", "DIqczzVBZ2ZUInnMR+MC2YK8BS5sAhxnLrGiVMhr/xd/SndHKL+TdyMDcRmgNu8BuVNHTJfrLgGwQ9FC9be2dhyFixYdQs3eshkZ70+Fkr79BUEifWEZ1FbzgNIwsuLUycqan6hR48IJwqLNA/GSrr/oFflUkRPWXCPnhDRnoUSlT5KXn0ifb8BO0U+0HnCw42pqORqMnxt/KAN7szh6tQ==")));
    }
}
